package com.chc.handler;

import com.chc.utils.Msg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Constants;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA
 *
 * @Author: chc
 * @Date: 2022/01/07/22:47
 * @Description:
 */
@Slf4j
//@RestControllerAdvice(basePackages = "com.chc.web")
public class GlobalExceptionHandler {
    /**
     * 处理请求参数格式错误 @RequestBody上validate失败后抛出的异常是MethodArgumentNotValidException异常
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Msg ValidateException(BindingResult bindingResult){
        //校验失败，应该返回失败，在模态框中显示校验失败的错误信息
        Map<String, Object> map = new HashMap<>(8);
        bindingResult.getFieldErrors().forEach(item -> map.put(item.getField(),item.getDefaultMessage()));
        log.error(String.valueOf(map));
        return Msg.error("数据校验出错",400,map);
    }

    /**
     * 处理Get请求中 使用@Valid 验证路径中请求实体校验失败后抛出的异常
     */

    @ExceptionHandler({BindException.class})
    public Msg ValidateException1(BindingResult bindingResult){
        //校验失败，应该返回失败，在模态框中显示校验失败的错误信息
        Map<String, Object> map = new HashMap<>(8);
        bindingResult.getFieldErrors().forEach(item -> map.put(item.getField(),item.getDefaultMessage()));
        log.error(String.valueOf(map));
        return Msg.error("数据校验出错",400,map);
    }


    /**
     * 处理请求参数格式错误 @RequestParam上validate失败后抛出的异常是ConstraintViolationException
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public Msg ValidateException(ConstraintViolationException e){
        // 获取异常信息
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        // 将异常信息收集到Map，key为校验失败的字段，value为失败原因
        Map<Path, String> map = constraintViolations.stream().collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage));
        // 返回校验失败信息
        return Msg.error("数据校验出错",400,map);
    }

    //处理其他异常类
    @ExceptionHandler({Exception.class})
    public Msg OtherException(Exception e){
        System.out.println("Exception");
        log.error(e.getMessage()+"------"+e.getClass());
        return Msg.error(e.getMessage());
    }
}
